// 一个宏任务在执行的过程中，是可以添加一些微任务的
// 例如
// 就像在柜台办理业务，你前边的一位老大爷可能在存款，在存款这个业务办理完以后
// 柜员会问老大爷还有没有其他需要办理的业务，这时老大爷想了一下
// “最近P2P爆雷有点儿多，是不是要选择稳一些的理财呢”，然后告诉柜员说，要办一些理财的业务，
// 这时候柜员肯定不能告诉老大爷说：“您再上后边取个号去，重新排队”。
// 在当前的微任务没有执行完成时，是不会执行下一个宏任务的。

// 宏任务 异步操作都可以称之为宏任务
// setTimeout
// setInterval
// setImmediate
// requestAnimationFrame

setTimeout((_) => console.log(4));

new Promise((resolve) => {
  resolve();
  console.log(1);
}).then((_) => {
  console.log(3);
  Promise.resolve()
    .then((_) => {
      console.log("before timeout");
    })
    .then((_) => {
      Promise.resolve().then((_) => {
        console.log("also before timeout");
      });
    });
});

console.log(2);

/*
  在前端开发中我们会通过setTimeout/setInterval来指定定时任务，会通过XHR/fetch发送网络请求，
  接下来简述一下setTimeout/setInterval和XHR/fetch到底做了什么事
  我们知道，不管是setTimeout/setInterval和XHR/fetch代码，在这些代码执行时，
  本身是同步任务，而其中的回调函数才是异步任务。
  当代码执行到setTimeout/setInterval时，实际上是JS引擎线程通知定时触发器线程，间隔一个时间后，会触发一个回调事件，
  而定时触发器线程在接收到这个消息后，会在等待的时间后，将回调事件放入到由事件触发线程所管理的事件队列中。
  当代码执行到XHR/fetch时，实际上是JS引擎线程通知异步http请求线程，发送一个网络请求，并制定请求完成后的回调事件，
  而异步http请求线程在接收到这个消息后，会在请求成功后，将回调事件放入到由事件触发线程所管理的事件队列中。
  当我们的同步任务执行完，JS引擎线程会询问事件触发线程，在事件队列中是否有待执行的回调函数，如果有就会加入到执行栈中交给JS引擎线程执行
*/

/*
代码呈现
*/

let timerCallback = function () {
  console.log("wait one second");
};
let httpCallback = function () {
  console.log("get server data success");
};

// 同步任务
console.log("hello");

// 同步任务
// 通知定时器线程 1s 后将 timerCallback 交由 事件触发线程 处理
// 1s 后事件触发线程将 timerCallback 加入到 事件队列 中
setTimeout(timerCallback, 1000);

// 同步任务
// 通知异步http请求线程发送网络请求，请求成功后将 httpCallback 交由事件触发线程处理
// 请求成功后事件触发线程将 httpCallback 加入到事件队列中
fetch("www.xxxx.com", httpCallback);
 
// 什么是宏任务? 
// 我们可以将每次执行栈执行的代码当作是一次宏任务 
// （包括每次从事件队列中获取一个事件回调并放到执行栈中执行）
//  每一个宏任务会从头到尾执行完毕，不会执行其他。
 